﻿using System;
using System.Collections.Generic;
using System.Text;
using Osteox.ManagedCv;

namespace inpaint
{
    class Program
    {
        static ManagedImage inpaint_mask = null;
        static Point2D32s prev_pt = new Point2D32s(-1, -1);
        static ManagedImage img0 = null;
        static ManagedImage img = null;
        static ManagedImage inpainted = null;

        static void on_mouse(WindowEventId eventid, int x, int y, WindowEventFlag flags, IntPtr data)
        {
            if (ManagedImage.IsNullOrInvalid(img0))
                return;

            if( eventid == WindowEventId.LButtonUp || (flags & WindowEventFlag.FlagLButton) == WindowEventFlag.None )
                prev_pt = new Point2D32s(-1,-1);
            else if( eventid == WindowEventId.LButtonDown )
                prev_pt = new Point2D32s(x,y);
            else if (eventid == WindowEventId.MouseMove && (flags & WindowEventFlag.FlagLButton) != WindowEventFlag.None)
            {
                Point2D32s pt = new Point2D32s(x,y);
                if( prev_pt.X < 0 )
                    prev_pt = pt;
                ManagedCvInvoke.Line(inpaint_mask, prev_pt, pt, ManagedCvInvoke.ScalarAll(255), 5, LineTypeFlag.Connected8, 0 );
                ManagedCvInvoke.Line(img, prev_pt, pt, ManagedCvInvoke.ScalarAll(255), 5, LineTypeFlag.Connected8, 0);
                prev_pt = pt;
                ManagedCvInvoke.ShowImage( "image", img );
            }
        }
        static void Main(string[] args)
        {
            string filename = args.Length >= 2 ? args[1] : "fruits.jpg";
            img0 = ManagedCvInvoke.LoadImageW(filename);
            if (NativeHandleObject.IsNullOrInvalid(img0))
            {
                return;
            }

            Console.WriteLine("Hot keys:");
            Console.WriteLine("\tESC - quit the program");
            Console.WriteLine("\tr - restore the original image");
            Console.WriteLine("\ti or SPACE - run inpainting algorithm");
            Console.WriteLine("\t\t(before running it, paint something on the image)");

            ManagedCvInvoke.NamedWindow("image", WindowMode.Autosize);

            img = ManagedCvInvoke.CloneImage(img0);
            inpainted = ManagedCvInvoke.CloneImage(img0);
            inpaint_mask = ManagedCvInvoke.CreateImage(ManagedCvInvoke.GetSize(img), PixelDepth.Depth8U, 1);

            ManagedCvInvoke.Zero(inpaint_mask);
            ManagedCvInvoke.Zero(inpainted);
            ManagedCvInvoke.ShowImage("image", img);
            ManagedCvInvoke.ShowImage("inpainted image", inpainted);
            ManagedCvInvoke.SetMouseCallback("image", on_mouse, IntPtr.Zero);

            for (; ; )
            {
                int c = ManagedCvInvoke.WaitKey(0);

                if ((char)c == 27)
                    break;

                if ((char)c == 'r')
                {
                    ManagedCvInvoke.Zero(inpaint_mask);
                    ManagedCvInvoke.Copy(img0, img);
                    ManagedCvInvoke.ShowImage("image", img);
                }

                if ((char)c == 'i' || (char)c == ' ')
                {
                    ManagedCvInvoke.NamedWindow("inpainted image", WindowMode.Autosize);
                    ManagedCvInvoke.Inpaint(img, inpaint_mask, inpainted, 3, InpaintType.TELEA);
                    ManagedCvInvoke.ShowImage("inpainted image", inpainted);
                }
            }
        }
    }
}
